Contexto:

En este proyecto sólo de mostrarán los métodos que conozco, estos métodos son utilizados para filtrar outliers, escalar datos, aplicar modelos de ML, etc. La idea es sólo mostrar los conocimientos y sé que algunos de estos sólo deben ser utilizados en determinadas circuntacias. Estas circuntacias serán asumidas, pero yo sé que se deben revisar estas, por ejemplo queremos utilizar un filtrado de outliers a través de z-score, entonces debemos verificar que los datos tengan distribución. Esto se puede realizar utilizando una gráfica Q-Q, un test de hipotesis como el test de Shapiro.

Fuentes de información:
https://www.kaggle.com/datasets/jacksondivakarr/phone-classification-dataset
https://www.kaggle.com/code/xkshitijx/using-randomforest-naivebayes/notebook

ML Life cycle
https://www.youtube.com/watch?v=xhB-dmKmzRk&ab_channel=KrishNaik
https://github.com/krishnaik06/Advanced-House-Price-Prediction-/blob/master/Exploratory%20Data%20Analysis%20Part%201.ipynb
https://neptune.ai/blog/life-cycle-of-a-machine-learning-project
https://www.datacamp.com/blog/machine-learning-lifecycle-explained
https://docs.aws.amazon.com/wellarchitected/latest/machine-learning-lens/well-architected-machine-learning-lifecycle.html

In [1]:
# Fase de análisis de los datos
import numpy as np
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats   
import pickle
import warnings
warnings.filterwarnings('ignore')
import os
import zipfile
import gdown

#if False:
if True:    
    # Outlier
    from sklearn.covariance import MinCovDet
    from sklearn.neighbors import LocalOutlierFactor
    from sklearn.linear_model import HuberRegressor, Ridge
    from sklearn.preprocessing import RobustScaler
    from sklearn.ensemble import IsolationForest
    from scipy.stats.mstats import winsorize


#if False:
if True:    
    # Fase de modelamiento de datos usando algoritmos de ML
    from sklearn.preprocessing import MinMaxScaler
    from sklearn.model_selection import GridSearchCV
    from sklearn.model_selection import train_test_split
    from sklearn.preprocessing import OneHotEncoder    

# escalamiento:
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import StandardScaler # estandarizacion normal 

# Modelos de ML
from sklearn.metrics import accuracy_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import MultinomialNB
from sklearn.neural_network import MLPClassifier
from sklearn.svm import LinearSVC
from sklearn import svm
from sklearn.neighbors import NearestCentroid
import xgboost as xgb

#Medidas de modelos ML
from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score
In [2]:
# Directorio 
!mkdir "Datos"
!mkdir "Resultados"
!mkdir "modelos"
Ya existe el subdirectorio o el archivo Datos.
Ya existe el subdirectorio o el archivo Resultados.
Ya existe el subdirectorio o el archivo modelos.

Opción para descargar los modelos entrenados y sus resultados inmediatamente.

In [ ]:
#if False:
if True:    
    def descomprimir(filename, destino):
        # Cargar archivo RAR
        with az.rar.RarArchive(filename) as archive:
            archive.extract_to_directory(destino)  

    # Datos
    drive_url = 'https://drive.google.com/drive/folders/1MkZlkvwg1YGYW-EI5CirL6lsRj3AN3Jy?usp=drive_link'
    output_name = "./Datos/Data_celulares.csv"
    gdown.download(drive_url, output_name, quiet=False)
    
    # Modelos notar que el archivo comprimido pesa 100Mb y descomprimido pesa aprox 600 Mb
    drive_url = 'https://drive.google.com/file/d/1IcxS17Lh_01LS2LAL1-BwbHOmhBb59Vl/view?usp=drive_link'
    output_name = ".modelosv2.rar"
    gdown.download(url=drive_url, output=output_name, fuzzy=True, quiet=False)
    
    # descomprimir el contenido de modelos.zip
    fantasy_zip = zipfile.ZipFile('./modelos.zip')
    fantasy_zip.extractall('./modelos/')
    fantasy_zip.close()
In [3]:
output_name = "./Datos/Data_celulares.csv"
data = pd.read_csv(output_name)
data.head(2)
Out[3]:
battery_power blue clock_speed dual_sim fc four_g int_memory m_dep mobile_wt n_cores ... px_height px_width ram sc_h sc_w talk_time three_g touch_screen wifi price_range
0 842 0 2.2 0 1 0 7 0.6 188 2 ... 20 756 2549 9 7 19 0 0 1 1
1 1021 1 0.5 1 0 1 53 0.7 136 3 ... 905 1988 2631 17 3 7 1 1 0 2

2 rows × 21 columns

Descripción de variable dependiente "price_range":¶

La variable dependiente "price_range" tiene valores 0,1,2 y 3. Cada uno de estos valores representa un intervalo de precios, en donde el valor 0 representa al intervalo de menor precio y el valor 3 representa el intervalo de mayor precio..

Cambio de valores de la variable dependiente "price_range":¶

In [4]:
orden_leyenda = ['Precio muy bajo','Precio bajo','Precio medio','Precio alto']
dict_orden={u:v for u,v in zip(list(range(0,4)),orden_leyenda)}

data["price_range_sort"]=data["price_range"]
data["price_range"]=data["price_range"].map(dict_orden)

# Ordenar el DataFrame según el orden deseado
data = data.sort_values(by='price_range_sort', ascending=True)
data.head(2)
Out[4]:
battery_power blue clock_speed dual_sim fc four_g int_memory m_dep mobile_wt n_cores ... px_width ram sc_h sc_w talk_time three_g touch_screen wifi price_range price_range_sort
1838 720 1 0.9 1 12 1 14 0.8 165 4 ... 1234 1086 14 7 3 1 1 0 Precio muy bajo 0
1762 808 1 0.5 1 3 0 46 0.5 105 8 ... 529 1082 15 5 10 1 0 1 Precio muy bajo 0

2 rows × 22 columns

Los seis pasos para entender el ciclo de vida de un proyecto de machine learning:

  • Data analysis
  • feacture engineering
  • Feacture selection
  • Model building
  • Model Deployment
  • Monitoring and Maintenance

Data analysis.¶

El objetivo del análisis de datos es encontrar lo siguiente:

  • Missing Values
  • Distribución de las variables númericas
  • Cardinilidad de las variables discretas
  • Outliers
  • Relaciones entre variables independientes v/s variables dependientes

Missing Values¶

In [5]:
print(data.isna().sum())
battery_power       0
blue                0
clock_speed         0
dual_sim            0
fc                  0
four_g              0
int_memory          0
m_dep               0
mobile_wt           0
n_cores             0
pc                  0
px_height           0
px_width            0
ram                 0
sc_h                0
sc_w                0
talk_time           0
three_g             0
touch_screen        0
wifi                0
price_range         0
price_range_sort    0
dtype: int64

Distribución de los datos¶

Tipo de datos de las Variables¶

In [6]:
data.info()
<class 'pandas.core.frame.DataFrame'>
Index: 2000 entries, 1838 to 1999
Data columns (total 22 columns):
 #   Column            Non-Null Count  Dtype  
---  ------            --------------  -----  
 0   battery_power     2000 non-null   int64  
 1   blue              2000 non-null   int64  
 2   clock_speed       2000 non-null   float64
 3   dual_sim          2000 non-null   int64  
 4   fc                2000 non-null   int64  
 5   four_g            2000 non-null   int64  
 6   int_memory        2000 non-null   int64  
 7   m_dep             2000 non-null   float64
 8   mobile_wt         2000 non-null   int64  
 9   n_cores           2000 non-null   int64  
 10  pc                2000 non-null   int64  
 11  px_height         2000 non-null   int64  
 12  px_width          2000 non-null   int64  
 13  ram               2000 non-null   int64  
 14  sc_h              2000 non-null   int64  
 15  sc_w              2000 non-null   int64  
 16  talk_time         2000 non-null   int64  
 17  three_g           2000 non-null   int64  
 18  touch_screen      2000 non-null   int64  
 19  wifi              2000 non-null   int64  
 20  price_range       2000 non-null   object 
 21  price_range_sort  2000 non-null   int64  
dtypes: float64(2), int64(19), object(1)
memory usage: 359.4+ KB
In [7]:
lista=["blue","dual_sim","four_g","three_g","touch_screen","wifi","price_range","price_range_sort"]

for columna in lista:
    data[columna] = data[columna].astype('category')    
data.info()
<class 'pandas.core.frame.DataFrame'>
Index: 2000 entries, 1838 to 1999
Data columns (total 22 columns):
 #   Column            Non-Null Count  Dtype   
---  ------            --------------  -----   
 0   battery_power     2000 non-null   int64   
 1   blue              2000 non-null   category
 2   clock_speed       2000 non-null   float64 
 3   dual_sim          2000 non-null   category
 4   fc                2000 non-null   int64   
 5   four_g            2000 non-null   category
 6   int_memory        2000 non-null   int64   
 7   m_dep             2000 non-null   float64 
 8   mobile_wt         2000 non-null   int64   
 9   n_cores           2000 non-null   int64   
 10  pc                2000 non-null   int64   
 11  px_height         2000 non-null   int64   
 12  px_width          2000 non-null   int64   
 13  ram               2000 non-null   int64   
 14  sc_h              2000 non-null   int64   
 15  sc_w              2000 non-null   int64   
 16  talk_time         2000 non-null   int64   
 17  three_g           2000 non-null   category
 18  touch_screen      2000 non-null   category
 19  wifi              2000 non-null   category
 20  price_range       2000 non-null   category
 21  price_range_sort  2000 non-null   category
dtypes: category(8), float64(2), int64(12)
memory usage: 251.1 KB
In [8]:
columnas=list(data.columns)
for col in columnas:
    print(col,"--->",
        data[col].dtypes  ,"--->",
        len(data[col].unique()))
battery_power ---> int64 ---> 1094
blue ---> category ---> 2
clock_speed ---> float64 ---> 26
dual_sim ---> category ---> 2
fc ---> int64 ---> 20
four_g ---> category ---> 2
int_memory ---> int64 ---> 63
m_dep ---> float64 ---> 10
mobile_wt ---> int64 ---> 121
n_cores ---> int64 ---> 8
pc ---> int64 ---> 21
px_height ---> int64 ---> 1137
px_width ---> int64 ---> 1109
ram ---> int64 ---> 1562
sc_h ---> int64 ---> 15
sc_w ---> int64 ---> 19
talk_time ---> int64 ---> 19
three_g ---> category ---> 2
touch_screen ---> category ---> 2
wifi ---> category ---> 2
price_range ---> category ---> 4
price_range_sort ---> category ---> 4

Distribución de los datos númericos¶

In [9]:
#if False:
if True:    
    columnas_numericas=data.select_dtypes(exclude=["category"]).columns
    columnas_category=data.select_dtypes(include=["category"]).columns
    label_prices=data["price_range"].unique()


    cant_rows=len(columnas_numericas) //2
    residuo=len(columnas_numericas) % 2
    if residuo == 1:
        cant_rows=cant_rows + 1 

    fig, axes = plt.subplots(nrows=cant_rows, ncols=2, figsize=(10, 20))

    for j in range(len(columnas_numericas)):
        feature=columnas_numericas[j]
        if "price_range"==feature:
            break
        num_row=j // 2
        num_col=j % 2
        
        for etiq in label_prices:
            sns.kdeplot(x=feature, data=data[data["price_range"]==etiq], ax=axes[num_row, num_col], label=etiq)    
        axes[num_row, num_col].grid()
        axes[num_row, num_col].set_title(feature+' v/s Density' )
        axes[num_row, num_col].set_xlabel(feature)
        axes[num_row, num_col].set_ylabel('Densidad')
        axes[num_row, num_col].legend(orden_leyenda,loc='upper left') 
        #plt.legend(orden_leyenda, loc='best')  # Aquí se usa el orden deseado en la leyenda
    plt.tight_layout()
    plt.show()

Distribución de datos de variables numéricas en los datos¶

In [10]:
#if False:
if True:        
    columnas_numericas=data.select_dtypes(exclude=["category"]).columns
    columnas_category=data.select_dtypes(include=["category"]).columns

    label_prices=data["price_range"].unique()


    cant_rows=len(columnas_numericas) //2
    residuo=len(columnas_numericas) % 2
    if residuo == 1:
        cant_rows=cant_rows + 1 

    fig, axes = plt.subplots(nrows=cant_rows, ncols=2, figsize=(10, 20))

    for j in range(len(columnas_numericas)):
        feature=columnas_numericas[j]
        num_row=j // 2
        num_col=j % 2
        
        sns.violinplot(x=feature, hue="price_range",data=data, ax=axes[num_row, num_col],hue_order=orden_leyenda)
        
        
        axes[num_row, num_col].grid()
        axes[num_row, num_col].set_title(feature+' v/s price range' )
        axes[num_row, num_col].set_xlabel(feature)
        axes[num_row, num_col].set_ylabel('Densidad')
        axes[num_row, num_col].legend(title="price_range", bbox_to_anchor=(1.05, 1), loc='upper left')
    
    plt.tight_layout()
    plt.show()
        

Proporción de los valores de los datos caso discreto.¶

In [11]:
#if False:
if True:        
#    sns.set_theme(style="whitegrid")
    
    columnas_numericas=list(data.select_dtypes(exclude=["category"]).columns)
    columnas_category=list(data.select_dtypes(include=["category"]).columns)

    label_prices=data["price_range"].unique()

    l_col=columnas_numericas[0:]
    for col in l_col:
        #fig = plt.figure(figsize=(3, 2))
        sns.displot( data, x=col, hue="price_range",kind="kde", multiple="fill" ,height=4, clip=(0, None), palette="ch:rot=-.25,hue=1,light=.75",hue_order=orden_leyenda)
        plt.show()

Proporción de los valores de los datos caso discreto.¶

In [12]:
#if False:
if True:        
    columnas_numericas=list(data.select_dtypes(exclude=["category"]).columns)
    columnas_category=list(data.select_dtypes(include=["category"]).columns)

    label_prices=data["price_range"].unique()

    l_col=columnas_numericas[0:]
    for col in l_col:
        fig = plt.figure(figsize=(5, 4))
        sns.histplot(data, x=col, hue="price_range", multiple="fill",hue_order=orden_leyenda)    
        plt.show()
        
In [13]:
value_counts_result = data.price_range.value_counts()
value_counts_result
Out[13]:
price_range
Precio alto        500
Precio bajo        500
Precio medio       500
Precio muy bajo    500
Name: count, dtype: int64

Detección de Outliers¶

Detección de Outlier sin filtar valores de la variable dependiente¶

In [14]:
if True:
#if False:    
    columnas_numericas=data.select_dtypes(exclude=["category"]).columns
    columnas_category=data.select_dtypes(include=["category"]).columns

    label_prices=data["price_range"].unique()


    cant_rows=len(columnas_numericas) //2
    residuo=len(columnas_numericas) % 2
    if residuo == 1:
        cant_rows=cant_rows + 1 


    fig, axes = plt.subplots(nrows=cant_rows, ncols=2, figsize=(8, 10))

    for j in range(len(columnas_numericas)):
        feature=columnas_numericas[j]
        num_row=j // 2
        num_col=j % 2
        
        sns.boxplot(x=feature, data=data, ax=axes[num_row, num_col])
        axes[num_row, num_col].set_title(feature+' v/s Density' )
        axes[num_row, num_col].set_xlabel(feature)
        axes[num_row, num_col].set_ylabel('Densidad')
    
    plt.tight_layout()
    plt.show()

Detección de Outlier filtando valores de la variable dependiente¶

In [15]:
if True:
#if False:    
    columnas_numericas=data.select_dtypes(exclude=["category"]).columns
    columnas_category=data.select_dtypes(include=["category"]).columns

    label_prices=data["price_range"].unique()


    cant_rows=len(columnas_numericas) //2
    residuo=len(columnas_numericas) % 2
    if residuo == 1:
        cant_rows=cant_rows + 1 


    fig, axes = plt.subplots(nrows=cant_rows, ncols=2, figsize=(10, 20))

    for j in range(len(columnas_numericas)):
        feature=columnas_numericas[j]
        num_row=j // 2
        num_col=j % 2
        
        sns.boxplot(x=feature, data=data,hue="price_range", ax=axes[num_row, num_col],hue_order=orden_leyenda)
        axes[num_row, num_col].set_title(feature+' v/s Density' )
        axes[num_row, num_col].set_xlabel(feature)
        axes[num_row, num_col].set_ylabel('Densidad')
        axes[num_row, num_col].legend(title="Price range", bbox_to_anchor=(1.05, 1), loc='upper left')
        #axes[num_row, num_col].legend(loc='upper left') 

    plt.tight_layout()
    plt.show()
        

Quitar outliers por:

  • Por cuartiles
  • z-score
  • trimming
  • winsorizing
  • minimum covariance determinant
  • local outlier factor
  • Huber and Ridge
  • isolation forest (tree-based algorithm)
In [16]:
# Forma 1: Por cuartiles
def cuartiles(df, columna, factor=1.4):
    
    Q1 = df[columna].quantile(0.25)
    Q3 = df[columna].quantile(0.75)
    IQR = Q3 - Q1

    # Definir el rango para identificar outliers
    lower_bound = Q1 - factor * IQR
    upper_bound = Q3 + factor * IQR
    
    df_filtrado = df[(df[columna] >= lower_bound) & (df[columna] <= upper_bound)]
    return df_filtrado.reset_index(drop=True)


# Forma 2: Por z-score.
def filtrar_outliers_zscore_dataframe(dataframe, columna, umbral=3):
    z_scores = np.abs(stats.zscore(dataframe[columna]))
    dataframe_filtrado = dataframe[(z_scores < umbral)]
    return dataframe_filtrado.reset_index(drop=True)

# Forma 3: Por trimming.
def filtrar_outliers_trimming(dataframe, columna,alpha=0.05):
    p_inf, p_sup =alpha/2, 1- alpha/2
    # Calcular los percentiles
    percentil_inf = dataframe[columna].quantile(p_inf)
    percentil_sup = dataframe[columna].quantile(p_sup)
    
    # Filtrar los datos dentro del rango de percentiles
    dataframe_filtrado = dataframe[(dataframe[columna] >= percentil_inf) & (dataframe[columna] <= percentil_sup)]
    return dataframe_filtrado.reset_index(drop=True)


# Forma 4: Por winsorizing
def filtrar_outliers_winsorizing(dataframe, columna,alpha=0.1):
    p_inf, p_sup =alpha/2, 1- alpha/2
    # Aplicar winsorizing a la columna
    columna_winsorizada = winsorize(dataframe[columna], limits=(p_inf, p_sup))
    
    # Reemplazar la columna original con la columna winsorizada
    dataframe[columna] = columna_winsorizada
    
    return dataframe.reset_index(drop=True)

# Forma 5: Por minimum covariance determinant
def filtrar_outliers_mcd(dataframe, columna, contamination=0.1):
    # Ajustar el modelo MCD a la columna especificada
    mcd = MinCovDet(random_state=0)
    mcd.fit(dataframe[[columna]])
    
    # Calcular la distancia de Mahalanobis para identificar outliers
    mahalanobis_distance = mcd.mahalanobis(dataframe[[columna]])
    
    # Filtrar el DataFrame manteniendo solo las filas que no son outliers
    dataframe_filtrado = dataframe[mahalanobis_distance <= mcd.location_outlier_threshold_]
    
    return dataframe_filtrado.reset_index(drop=True)

# Forma 6: Por local outlier factor
def filtrar_outliers_lof(dataframe, columna, contaminacion=0.1):
    # Ajustar el modelo LOF a la columna especificada
    lof = LocalOutlierFactor(contamination=contaminacion)
    outliers = lof.fit_predict(dataframe[[columna]])
    
    # Filtrar el DataFrame manteniendo solo las filas que no son outliers
    dataframe_filtrado = dataframe[outliers != -1]
    
    return dataframe_filtrado.reset_index(drop=True)


# Forma 7: Por Huber and Ridge
def filtrar_outliers_huber(df, var_indep,target,umbral=3):
    # Establecer un umbral para identificar outliers (puedes ajustar este valor según tus necesidades)
    # umbral = 3  # Por ejemplo, utilizando 3 desviaciones estándar
    X = df[[var_indep]]
    y = df[target]

    # Escalar los datos utilizando RobustScaler para hacerlos robustos a los outliers
    scaler = RobustScaler()
    X_scaled = scaler.fit_transform(X)

    # Crear modelos de regresión Huber y Ridge
    huber_reg = HuberRegressor()
    huber_reg.fit(X_scaled, y)
    y_pred_huber = huber_reg.predict(X_scaled)
    
    # Calcular los residuos para identificar outliers
    residuos_huber = abs(y - y_pred_huber)
    
    # Filtrar outliers utilizando los residuos y el umbral
    df_filtrado_huber = df[residuos_huber < umbral]
    return df_filtrado_huber.reset_index(drop=True)

def filtrar_outliers_ridge(df, var_indep,target,umbral=3):
    # Establecer un umbral para identificar outliers (puedes ajustar este valor según tus necesidades)
    # umbral = 3  # Por ejemplo, utilizando 3 desviaciones estándar
    # Separar las características y la variable objetivo
    X = df[[var_indep]]
    y = df[target]
    # Escalar los datos utilizando RobustScaler para hacerlos robustos a los outliers
    scaler = RobustScaler()
    X_scaled = scaler.fit_transform(X)
    # Crear modelos de regresión Ridge
    ridge_reg = Ridge(alpha=1.0)
    ridge_reg.fit(X_scaled, y)
    y_pred_ridge = ridge_reg.predict(X_scaled)
    residuos_ridge = abs(y - y_pred_ridge) # Calcular los residuos para identificar outliers

    df_filtrado_ridge = df[residuos_ridge < umbral] # Filtrar outliers utilizando los residuos y el umbral
    return df_filtrado_ridge.reset_index(drop=True)

# Forma 8: Por isolation forest (tree-based algorithm)
def filtrar_outliers_lof(df, columna, contaminacion=0.1):
    X = df[columna]

    # Crear y ajustar el modelo Isolation Forest
    isoforest = IsolationForest(contamination=contaminacion, random_state=42)
    isoforest.fit(X)

    pred_anomalias = isoforest.predict(X)
    df['Outlier'] = pred_anomalias
    df_filtrado = df[df['Outlier'] == 1]  # -1 indica que es outlier, 1 indica que no es outlier
    df_filtrado = df_filtrado.drop(columns=['Outlier'])
    return df_filtrado.reset_index(drop=True)

l_function_name=["cuartiles","filtrar_outliers_zscore_dataframe","filtrar_outliers_trimming","filtrar_outliers_winsorizing","filtrar_outliers_mcd","filtrar_outliers_lof","filtrar_outliers_huber","filtrar_outliers_ridge","filtrar_outliers_lof"]
l_function=[cuartiles,filtrar_outliers_zscore_dataframe,filtrar_outliers_trimming,filtrar_outliers_winsorizing,filtrar_outliers_mcd,filtrar_outliers_lof,filtrar_outliers_huber,filtrar_outliers_ridge,filtrar_outliers_lof]
dict_function_outlier={u:v for u,v in zip(l_function_name,l_function)}


with open("data.pickle", "wb") as archivo:
    pickle.dump(data, archivo)
In [17]:
with open("data.pickle", "rb") as archivo:
    data = pickle.load(archivo)    

list_cols_outiliers=["fc","int_memory","ram","px_height"] # columnas con outliers
imagen_price_range=list(data["price_range"].value_counts().index)
factor=1.4 # factor que determina que tan estricto es para eliminar outliers (más alto más estricto)

dict_df={}
target="price_range_sort"


for name_met_outlier in list(dict_function_outlier.keys()):
    df1=data.copy()
    
    for col in list_cols_outiliers:
        for price in imagen_price_range:
            mascara=df1["price_range"]==price
            df2=df1[mascara].reset_index(drop=True)
            # inicio
            if "filtrar_outliers_mcd"==name_met_outlier or "filtrar_outliers_lof"==name_met_outlier or "filtrar_outliers_huber"==name_met_outlier:
                break
            f_met_outlier=dict_function_outlier[name_met_outlier]
            if "filtrar_outliers_huber"==name_met_outlier or "filtrar_outliers_ridge"==name_met_outlier:
                break
                data_sin_outliers = f_met_outlier(df2, col,target)
            else:
                data_sin_outliers = f_met_outlier(df2, col)
            dimension=data_sin_outliers.shape

            if dimension[0]!=0:
                df1=pd.concat([data_sin_outliers,df1[~mascara]]).reset_index(drop=True)
            else:
                df1=df1[~mascara].reset_index(drop=True)
        
            # fin
         
    # guardar dataframe filtrado:
    
    if df1.shape[0]< data.shape[0]:
        # dejar datos en su version normal
        nombres_nuevos = {"Precio muy bajo":0, "Precio bajo":1, "Precio medio":2, "Precio alto":3}
        df1['price_range'] = df1['price_range'].replace(nombres_nuevos)
        df1['price_range'] = df1['price_range'].astype('category')
        df1 = df1.drop(columns=['price_range_sort'])
        
        # Agregar al dataframe 
        dict_df[name_met_outlier]=df1
    

with open("dict_df_outlier.pickle", "wb") as archivo:
    pickle.dump(dict_df, archivo)

print("Tamaño del DataFrame original:", data.shape," \n ")
for name,dataframev in zip(dict_df.keys(),dict_df.values()):
    # Mostrar la forma del DataFrame original y el DataFrame sin outliers
    print("Tamaño del DataFrame de ",name,": ", dataframev.shape)     
Tamaño del DataFrame original: (2000, 22)  
 
Tamaño del DataFrame de  cuartiles :  (1920, 21)
Tamaño del DataFrame de  filtrar_outliers_zscore_dataframe :  (1983, 21)
Tamaño del DataFrame de  filtrar_outliers_trimming :  (1701, 21)

Revisión de quitar los outlier por método: filtrar_outliers_trimming¶

Filtrando en función de la variable dependiente

In [18]:
with open("dict_df_outlier.pickle", "rb") as archivo:
    dict_cargado = pickle.load(archivo)    

data=dict_cargado["filtrar_outliers_trimming"]
orden_leyenda = ['Precio muy bajo','Precio bajo','Precio medio','Precio alto']
dict_orden={u:v for u,v in zip(list(range(0,4)),orden_leyenda)}
data["price_range_sort"]=data["price_range"]
data["price_range"]=data["price_range"].map(dict_orden)


if True:
#if False:    
    columnas_numericas=data.select_dtypes(exclude=["category"]).columns
    columnas_category=data.select_dtypes(include=["category"]).columns

    label_prices=data["price_range"].unique()


    cant_rows=len(columnas_numericas) //2
    residuo=len(columnas_numericas) % 2
    if residuo == 1:
        cant_rows=cant_rows + 1 


    fig, axes = plt.subplots(nrows=cant_rows, ncols=2, figsize=(10, 20))

    for j in range(len(columnas_numericas)):
        feature=columnas_numericas[j]
        num_row=j // 2
        num_col=j % 2
        
        sns.boxplot(x=feature, data=data,hue="price_range", ax=axes[num_row, num_col],hue_order=orden_leyenda)
        axes[num_row, num_col].set_title(feature+' v/s Density' )
        axes[num_row, num_col].set_xlabel(feature)
        axes[num_row, num_col].set_ylabel('Densidad')
        axes[num_row, num_col].legend(title="Price range", bbox_to_anchor=(1.05, 1), loc='upper left')
        #axes[num_row, num_col].legend(loc='upper left') 

    plt.tight_layout()
    plt.show()
        
In [ ]:
 

Estudio multivariable¶

In [19]:
if True:
#if False:    
    
    with open("dict_df_outlier.pickle", "rb") as archivo:
        dict_cargado = pickle.load(archivo)    

    data=dict_cargado["filtrar_outliers_trimming"]
    orden_leyenda = ['Precio muy bajo','Precio bajo','Precio medio','Precio alto']
    dict_orden={u:v for u,v in zip(list(range(0,4)),orden_leyenda)}
    data["price_range_sort"]=data["price_range"]
    data["price_range"]=data["price_range"].map(dict_orden)

    columnas_numericas=list(data.select_dtypes(exclude=["category"]).columns)
    columnas_numericas.append("price_range")

    columnas_category=data.select_dtypes(include=["category"]).columns

    sns.pairplot( data = data[list(columnas_numericas)],hue="price_range")
    plt.tight_layout()
    plt.show()

Estudio de correlaciones entre variables:¶

Ver correlaciones de las variables en escala normal:

In [20]:
with open("dict_df_outlier.pickle", "rb") as archivo:
    dict_cargado = pickle.load(archivo)

data=dict_cargado["filtrar_outliers_trimming"]

umbral = 0.03
corr_matrix=abs(data.corr())
boolean_matrix =np.where(corr_matrix < umbral, True, False)

fig = plt.figure()                    
sns.heatmap(-corr_matrix, cmap='mako', mask=boolean_matrix)
plt.show()

Ver correlaciones de las variables en escala logaritmica:

In [21]:
with open("dict_df_outlier.pickle", "rb") as archivo:
    dict_cargado = pickle.load(archivo)    

data=dict_cargado["filtrar_outliers_trimming"]

umbral = 3.5
corr_matrix= -np.log(abs(data.corr()))
boolean_matrix = np.where(corr_matrix < umbral, False,True)

fig = plt.figure()
sns.heatmap(corr_matrix, cmap='mako', mask=boolean_matrix)
plt.show()

Ejemplo de eliminación de variables no correlacionadas con la variable dependiente:

In [22]:
with open("dict_df_outlier.pickle", "rb") as archivo:
    dict_cargado = pickle.load(archivo)    

data=dict_cargado["filtrar_outliers_trimming"]


data_correl=data
umbral = 3.5
corr_matrix= -np.log(abs(data_correl.corr()))
boolean_matrix = np.where(corr_matrix < umbral, False,True)

for col,aff in zip(list(data_correl.columns),list(boolean_matrix[-1,:])):   # list(boolean_matrix[-1,:]) fila correspondiente a la var dep
    if aff==True:
        data_correl = data_correl.drop(col, axis = 1)

corr_matrix= -np.log(abs(data_correl.corr()))
boolean_matrix = np.where(corr_matrix < umbral, False,True)

fig = plt.figure()
sns.heatmap(corr_matrix, cmap='mako', mask=boolean_matrix)
plt.show()
In [23]:
umbral = 3.5

with open("dict_df_outlier.pickle", "rb") as archivo:
    dict_cargado = pickle.load(archivo)    

for outlier_method in list(dict_cargado.keys()):
    #outlier_method="filtrar_outliers_trimming"
    data_correl=dict_cargado[outlier_method]  # bs_data: data paso anterior del método que tiene el nombre==keys
    method_dict={}
    # Caso: quitamos var indep poco correlacionadas con var dep
    corr_matrix= -np.log(abs(data_correl.corr()))
    boolean_matrix = np.where(corr_matrix < umbral, False,True)

    for col,aff in zip(list(data_correl.columns),list(boolean_matrix[-1,:])):   # list(boolean_matrix[-1,:]) fila correspondiente a la var dep    
        if aff==True:
            data_correl = data_correl.drop(col, axis = 1)

    method_dict["filtrado_correlacion"]=data_correl

# Caso: No quitamos var indep poco correlacionadas con var dep
    method_dict["no_filtrado_correlacion"]=dict_cargado[outlier_method]

    # agregamos un dict al dict del nivel anterior
    dict_cargado[outlier_method]=method_dict

with open("dict_df_correl.pickle", "wb") as archivo:
    pickle.dump(dict_cargado, archivo)    

Algoritmos ML¶

División del conjunto de datos

Forma de escalar datos:

  • Escalamiento de datos vía normalización
  • Escalamiento de datos vía rango [a, b]
  • Escalamiento de datos vía estandarización
  • Escalamiento de datos vía estandarización robusta
  • Escalamiento de datos diferenciada
In [24]:
def escaled_min_max(data,columna):
    XX = data.drop([columna], axis = 1)
    y = data[columna]

    dato_dummies=pd.get_dummies(XX)    
    scaler = MinMaxScaler(feature_range=(0, 1)).fit_transform(dato_dummies)

    X = pd.DataFrame(scaler, columns=dato_dummies.columns)
    X_train , X_test , Y_train , Y_test = train_test_split(X,y,test_size= 0.2 ,shuffle=True , random_state=1)

    y_one_hot_train = pd.get_dummies(Y_train).astype(int)
    y_one_hot_test = pd.get_dummies(Y_test).astype(int)

    return X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test

def escaled_Standardization(data,columna):
    XX = data.drop([columna], axis = 1)
    y = data[columna]

    dato_dummies=pd.get_dummies(XX)    
    scaler = StandardScaler().fit_transform(dato_dummies)

    X = pd.DataFrame(scaler, columns=dato_dummies.columns)
    X_train , X_test , Y_train , Y_test = train_test_split(X,y,test_size= 0.2 ,shuffle=True , random_state=1)

    y_one_hot_train = pd.get_dummies(Y_train).astype(int)
    y_one_hot_test = pd.get_dummies(Y_test).astype(int)

    return X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test


def robust_escaled_Standardization(data,columna):
    XX = data.drop([columna], axis = 1)
    y = data[columna]

    dato_dummies=pd.get_dummies(XX)    
    scaler = RobustScaler().fit_transform(dato_dummies)

    X = pd.DataFrame(scaler, columns=dato_dummies.columns)
    X_train , X_test , Y_train , Y_test = train_test_split(X,y,test_size= 0.2 ,shuffle=True , random_state=1)

    y_one_hot_train = pd.get_dummies(Y_train).astype(int)
    y_one_hot_test = pd.get_dummies(Y_test).astype(int)

    return X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test


def without_escaled(data,columna):
    XX = data.drop([columna], axis = 1)
    y = data[columna]

    dato_dummies=pd.get_dummies(XX).astype(float)
    
    X_train , X_test , Y_train , Y_test = train_test_split(dato_dummies,y,test_size= 0.2 ,shuffle=True , random_state=1)

    y_one_hot_train = pd.get_dummies(Y_train).astype(int)
    y_one_hot_test = pd.get_dummies(Y_test).astype(int)

    return X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test

def diferenciado_escaled_min_max(data,columna):
    target_values = data[columna].unique()
    XX = data.drop([columna], axis = 1)
    y = data[columna]


    dato_dummies=pd.get_dummies(XX)      # data a filtrar
    var_indep=list(set(list(dato_dummies.columns))-set(columna))

    dato_dummies["price_range"]=y   

    for target_value in target_values:
        mask1=dato_dummies[columna] == target_value
        subset_df = dato_dummies[mask1]

        # Aplicar el escalado Min-Max a las columnas numéricas del subconjunto
        scaler = MinMaxScaler()
        subset_df[var_indep] = scaler.fit_transform(subset_df[var_indep])
        dato_dummies[mask1] = subset_df
    
    
    y = dato_dummies[columna]
    dato_dummies = dato_dummies.drop([columna], axis = 1).astype(float)

    X = pd.DataFrame(dato_dummies, columns=dato_dummies.columns)
    X_train , X_test , Y_train , Y_test = train_test_split(X,y,test_size= 0.2 ,shuffle=True , random_state=1)

    y_one_hot_train = pd.get_dummies(Y_train).astype(int)
    y_one_hot_test = pd.get_dummies(Y_test).astype(int)

    return X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test


def diferenciado_escaled_Standardization(data,columna):
    target_values = data[columna].unique()
    XX = data.drop([columna], axis = 1)
    y = data[columna]


    dato_dummies=pd.get_dummies(XX)      # data a filtrar
    var_indep=list(set(list(dato_dummies.columns))-set(columna))

    dato_dummies["price_range"]=y   

    for target_value in target_values:
        mask1=dato_dummies[columna] == target_value
        subset_df = dato_dummies[mask1]

        # Aplicar el escalado Min-Max a las columnas numéricas del subconjunto
        scaler = StandardScaler()
        subset_df[var_indep] = scaler.fit_transform(subset_df[var_indep])
        dato_dummies[mask1] = subset_df

    y = dato_dummies[columna]
    dato_dummies = dato_dummies.drop([columna], axis = 1).astype(float)

    X = pd.DataFrame(dato_dummies, columns=dato_dummies.columns)
    X_train , X_test , Y_train , Y_test = train_test_split(X,y,test_size= 0.2 ,shuffle=True , random_state=1)

    y_one_hot_train = pd.get_dummies(Y_train).astype(int)
    y_one_hot_test = pd.get_dummies(Y_test).astype(int)

    return X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test


def diferenciado_robust_escaled_Standardization(data,columna):
    target_values = data[columna].unique()
    XX = data.drop([columna], axis = 1)
    y = data[columna]


    dato_dummies=pd.get_dummies(XX)      # data a filtrar
    var_indep=list(set(list(dato_dummies.columns))-set(columna))

    dato_dummies["price_range"]=y   

    for target_value in target_values:
        mask1=dato_dummies[columna] == target_value
        subset_df = dato_dummies[mask1]

        # Aplicar el escalado Min-Max a las columnas numéricas del subconjunto
        scaler = RobustScaler()
        subset_df[var_indep] = scaler.fit_transform(subset_df[var_indep])
        dato_dummies[mask1] = subset_df

    y = dato_dummies[columna]
    dato_dummies = dato_dummies.drop([columna], axis = 1).astype(float)
    X = pd.DataFrame(dato_dummies, columns=dato_dummies.columns)
    X_train , X_test , Y_train , Y_test = train_test_split(X,y,test_size= 0.2 ,shuffle=True , random_state=1)

    y_one_hot_train = pd.get_dummies(Y_train).astype(int)
    y_one_hot_test = pd.get_dummies(Y_test).astype(int)

    return X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test
In [25]:
with open("dict_df_correl.pickle", "rb") as archivo:
    dict_cargado = pickle.load(archivo)  

columna="price_range"
# outlier-> correlacion -> escalamiento


for outlier_method in list(dict_cargado.keys()):
    for name_correl_dict in dict_cargado[outlier_method].keys():
        
        data=dict_cargado[outlier_method][name_correl_dict]

        escalamiento_dict={}
        
        # escalamiento 1
        X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test=escaled_min_max(data,columna)
        escalamiento_dict["escaled_min_max"]=[X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test]

        # escalamiento 2
        X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test=escaled_Standardization(data,columna)
        escalamiento_dict["escaled_Standardization"]=[X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test]

        # escalamiento 3
        X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test=robust_escaled_Standardization(data,columna)
        escalamiento_dict["robust_escaled_Standardization"]=[X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test]

        # escalamiento 4
        X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test=diferenciado_escaled_min_max(data,columna)
        escalamiento_dict["diferenciado_escaled_min_max"]=[X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test]

        # escalamiento 5
        X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test=diferenciado_escaled_Standardization(data,columna)
        escalamiento_dict["diferenciado_escaled_Standardization"]=[X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test]
        
        # escalamiento 6
        X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test=diferenciado_robust_escaled_Standardization(data,columna)
        escalamiento_dict["diferenciado_robust_escaled_Standardization"]=[X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test]
        
        # escalamiento 7
        X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test=without_escaled(data,columna)
        escalamiento_dict["without_escaled"]=[X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test]
        
        # fin escalamiento 
        dict_cargado[outlier_method][name_correl_dict]=escalamiento_dict


with open("dict_df_scaled.pickle", "wb") as archivo:
    pickle.dump(dict_cargado, archivo)

Ejecutar los modelos de ml para todas las datas¶

Definir grid de parametros para cada algoritmo de ML

In [27]:
dict_parameter={}
#  Random Forest
parameters = {
    'n_estimators' : [50, 150, 500],
    'criterion' : ['gini', 'entropy', 'log_loss'],
    'max_features' : ['sqrt', 'log2'],
    'n_jobs':[-1]
}
dict_parameter["Ramdon Forest"]=(RandomForestClassifier(random_state=20),parameters)

#  MultinomialNB
parameters = {
    'alpha' : [1e-0,1e-1,1e-2,1e-3,1e-4],
    'fit_prior' : [True,False]
}
dict_parameter["MultinomialNB"]=(MultinomialNB(),parameters)

# MLPClassifier
model=MLPClassifier()
parameters = {
    "activation":["identity","logistic","tanh","relu"],
    "solver":["lbfgs","sgd","adam"],
    "learning_rate":["constant","invscaling","adaptive"]
}
dict_parameter["MLPClassifier"]=(model,parameters)

# LinearSVC
model=LinearSVC()
parameters = {
    "penalty":["l1","l2"],
    "loss":["hinge","squared_hinge"],
    "C":[1e2,1e1,1e-1,1e-2],
    "max_iter":[1000],
    "intercept_scaling":[False, True],
    "multi_class":["ovr","crammer_singer"]
}
dict_parameter["LinearSVC"]=(model,parameters)

# svm.NuSVC
model=svm.NuSVC(gamma="auto")
parameters = {
    "kernel":["linear","poly","rbf","sigmoid"],
    "degree":[1,3,5,7]
}
dict_parameter["svm.NuSVC"]=(model,parameters)

# NearestCentroid
model=NearestCentroid()
parameters = { }
dict_parameter["NearestCentroid"]=(model,parameters)

# xgb.XGBClassifier
model=xgb.XGBClassifier(
    objective='binary:logistic',  # 'multi:softmax' para clasificación multiclase
    eval_metric='logloss',         # Métrica de evaluación
    use_label_encoder=False        # Desactivar la codificación automática de etiquetas
    )
parameters = {
    "kernel":["linear","poly","rbf","sigmoid"],
    "degree":[1,2,3,4,5,6,7]
}
dict_parameter["xgb.XGBClassifier"]=(model,parameters)

dict_parameter.keys()    
Out[27]:
dict_keys(['Ramdon Forest', 'MultinomialNB', 'MLPClassifier', 'LinearSVC', 'svm.NuSVC', 'NearestCentroid', 'xgb.XGBClassifier'])
In [28]:
def grid_para_model_ml(model_name,Model,fold_cv,parameters,X_train,Y_train,X_test,Y_test,y_one_hot_train,y_one_hot_test):
    
    models_one_hot = ["MultinomialNB", "LinearSVC", "svm.NuSVC", "NearestCentroid"]

    if model_name not in models_one_hot:
        model_grid = GridSearchCV(estimator=Model, cv=fold_cv, param_grid=parameters).fit(X_train , y_one_hot_train)
        best_model=model_grid.best_estimator_
        
        print("\n" ,"Modelo:",model_name )
        y_pred_train=best_model.predict(X_train)
        eva_train=precision_score(y_one_hot_train, y_pred_train, average='micro')
        print("Presición modelo (Train):",eva_train)
        
        y_pred_test=best_model.predict(X_test)
        eva_test=precision_score(y_one_hot_test, y_pred_test, average='micro')
        print("Presición modelo (Test):",eva_test)

        accuracy = accuracy_score(y_one_hot_test, y_pred_test)
        precision = precision_score(y_one_hot_test, y_pred_test, average='macro')
        recall = recall_score(y_one_hot_test, y_pred_test, average='macro')
        f1 = f1_score(y_one_hot_test, y_pred_test, average='macro')

    else:
        model_grid = GridSearchCV(estimator=Model, cv=fold_cv, param_grid=parameters).fit(X_train , Y_train)
        best_model=model_grid.best_estimator_
        
        print("\n" ,"Modelo:",model_name )
        y_pred_train=best_model.predict(X_train)
        eva_train=precision_score(Y_train, y_pred_train, average='micro')
        print("Presición modelo (Train):",eva_train)
        
        y_pred_test=best_model.predict(X_test)
        eva_test=precision_score(Y_test, y_pred_test, average='micro')
        print("Presición modelo (Test):",eva_test)

        accuracy = accuracy_score(Y_test, y_pred_test)
        precision = precision_score(Y_test, y_pred_test, average='macro')
        recall = recall_score(Y_test, y_pred_test, average='macro')
        f1 = f1_score(Y_test, y_pred_test, average='macro')        

    return best_model,eva_train,eva_test,accuracy,precision,recall,f1
In [29]:
def medidas_models(outlier_method,dict_cargado,fold_cv,dict_parameter):
    # PArt 1: Sirve para cargar checkpoint del progeso del código.
    ruta_archivo = 'progreso.pickle'
    if os.path.exists(ruta_archivo):
        with open(ruta_archivo, "rb") as archivo:
            dict_progreso = pickle.load(archivo)    

            if outlier_method in set(dict_progreso.keys()):
                num_progreso=dict_progreso[outlier_method]
            else:
                num_progreso=-1
    else:
        dict_progreso={}
        num_progreso=-1

    count=0
    for name_correl_dict in dict_cargado[outlier_method].keys():
        for dict_scaled_name in dict_cargado[outlier_method][name_correl_dict].keys():
            if num_progreso >= count:
                count+=1
                continue
                
            if dict_scaled_name=="without_escaled":
                continue

            X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test=dict_cargado[outlier_method][name_correl_dict][dict_scaled_name]  # datas escaladas
            dict_eva_model={}
            with open("archivo.txt", "w") as archivo:
                archivo.write(str(count)+", "+outlier_method+", "+dict_scaled_name+", "+name_correl_dict)

            for model_name in list(dict_parameter.keys()):
                    print("dict_scaled_name",dict_scaled_name,"model_name",model_name)
                    (model,parameters)=dict_parameter[model_name]
                    if model_name=="MultinomialNB":
                        if dict_scaled_name in {"escaled_Standardization","robust_escaled_Standardization","diferenciado_escaled_Standardization","diferenciado_robust_escaled_Standardization","diferenciado_escaled_min_max"}:
                            continue
                        
                    best_model,eva_train,eva_test,accuracy,precision,recall,f1=grid_para_model_ml(model_name,model,fold_cv,parameters,X_train,Y_train,X_test,Y_test,y_one_hot_train,y_one_hot_test)
                    dict_eva_model[model_name]={"best_model":best_model,"eva_train":eva_train,"eva_test":eva_test,"accuracy":accuracy,"precision":precision,"recall":recall,"f1":f1}
                    
            with open("./modelos/"+outlier_method+name_correl_dict+dict_scaled_name+".pickle", "wb") as archivo:
                pickle.dump(dict_eva_model, archivo) 
            
            
            dict_progreso[outlier_method]=count  # marcar iteracion que esta lista
            count+=1                             # establecer siguiente iteracion a realizar
            with open("progreso.pickle", "wb") as archivo: # progreso
                pickle.dump(dict_progreso, archivo)                 
                        
            dict_cargado[outlier_method][name_correl_dict][dict_scaled_name]={"Datos":[X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test]}
            dict_cargado[outlier_method][name_correl_dict][dict_scaled_name]["Dict Modelos"]=dict_eva_model
            

    with open(outlier_method+"dict_df_modelos.pickle", "wb") as archivo:
        pickle.dump(dict_cargado, archivo) 

Entrenamiento de cada modelo para cada data¶

In [30]:
#if False:
if True:    
    with open("dict_df_scaled.pickle", "rb") as archivo:
        dict_cargado = pickle.load(archivo)  

    fold_cv=5

    for outlier_method in list(dict_cargado.keys()):
        medidas_models(outlier_method,dict_cargado,fold_cv,dict_parameter)
In [31]:
def juntar_medidas_models(dict_cargado):
    
    for outlier_method in dict_cargado.keys():
        for name_correl_dict in dict_cargado[outlier_method].keys():
            for dict_scaled_name in dict_cargado[outlier_method][name_correl_dict].keys():
                
                if dict_scaled_name=="without_escaled":
                    continue
                X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test=dict_cargado[outlier_method][name_correl_dict][dict_scaled_name]  # datas escaladas

                with open("./modelos/"+outlier_method+name_correl_dict+dict_scaled_name+".pickle", "rb") as archivo:
                    dict_eva_model = pickle.load(archivo)             
                
                dict_cargado[outlier_method][name_correl_dict][dict_scaled_name]={"Datos":[X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test]}
                dict_cargado[outlier_method][name_correl_dict][dict_scaled_name]["Dict Modelos"]=dict_eva_model
                print(outlier_method,name_correl_dict,dict_scaled_name)

    with open("./Resultados/dict_df_modelos_all.pickle", "wb") as archivo:
        pickle.dump(dict_cargado, archivo) 
In [32]:
with open("./Resultados/dict_df_scaled.pickle", "rb") as archivo:
    dict_cargado = pickle.load(archivo) 
juntar_medidas_models(dict_cargado)
cuartiles filtrado_correlacion escaled_min_max
cuartiles filtrado_correlacion escaled_Standardization
cuartiles filtrado_correlacion robust_escaled_Standardization
cuartiles filtrado_correlacion diferenciado_escaled_min_max
cuartiles filtrado_correlacion diferenciado_escaled_Standardization
cuartiles filtrado_correlacion diferenciado_robust_escaled_Standardization
cuartiles no_filtrado_correlacion escaled_min_max
cuartiles no_filtrado_correlacion escaled_Standardization
cuartiles no_filtrado_correlacion robust_escaled_Standardization
cuartiles no_filtrado_correlacion diferenciado_escaled_min_max
cuartiles no_filtrado_correlacion diferenciado_escaled_Standardization
cuartiles no_filtrado_correlacion diferenciado_robust_escaled_Standardization
filtrar_outliers_zscore_dataframe filtrado_correlacion escaled_min_max
filtrar_outliers_zscore_dataframe filtrado_correlacion escaled_Standardization
filtrar_outliers_zscore_dataframe filtrado_correlacion robust_escaled_Standardization
filtrar_outliers_zscore_dataframe filtrado_correlacion diferenciado_escaled_min_max
filtrar_outliers_zscore_dataframe filtrado_correlacion diferenciado_escaled_Standardization
filtrar_outliers_zscore_dataframe filtrado_correlacion diferenciado_robust_escaled_Standardization
filtrar_outliers_zscore_dataframe no_filtrado_correlacion escaled_min_max
filtrar_outliers_zscore_dataframe no_filtrado_correlacion escaled_Standardization
filtrar_outliers_zscore_dataframe no_filtrado_correlacion robust_escaled_Standardization
filtrar_outliers_zscore_dataframe no_filtrado_correlacion diferenciado_escaled_min_max
filtrar_outliers_zscore_dataframe no_filtrado_correlacion diferenciado_escaled_Standardization
filtrar_outliers_zscore_dataframe no_filtrado_correlacion diferenciado_robust_escaled_Standardization
filtrar_outliers_trimming filtrado_correlacion escaled_min_max
filtrar_outliers_trimming filtrado_correlacion escaled_Standardization
filtrar_outliers_trimming filtrado_correlacion robust_escaled_Standardization
filtrar_outliers_trimming filtrado_correlacion diferenciado_escaled_min_max
filtrar_outliers_trimming filtrado_correlacion diferenciado_escaled_Standardization
filtrar_outliers_trimming filtrado_correlacion diferenciado_robust_escaled_Standardization
filtrar_outliers_trimming no_filtrado_correlacion escaled_min_max
filtrar_outliers_trimming no_filtrado_correlacion escaled_Standardization
filtrar_outliers_trimming no_filtrado_correlacion robust_escaled_Standardization
filtrar_outliers_trimming no_filtrado_correlacion diferenciado_escaled_min_max
filtrar_outliers_trimming no_filtrado_correlacion diferenciado_escaled_Standardization
filtrar_outliers_trimming no_filtrado_correlacion diferenciado_robust_escaled_Standardization

Ejemplo: modelo NearestCentroid usando datos filtrados usando correlación,escala mín y max, y sus outliers filtrador por cuartiles

In [33]:
with open("./Resultados/dict_df_modelos_all.pickle", "rb") as archivo:
    dict_cargado = pickle.load(archivo) 
dict_cargado["cuartiles"]["filtrado_correlacion"]["escaled_min_max"]['Dict Modelos']["NearestCentroid"]
Out[33]:
{'best_model': NearestCentroid(),
 'eva_train': 0.67578125,
 'eva_test': 0.6223958333333334,
 'accuracy': 0.6223958333333334,
 'precision': 0.6449419787749214,
 'recall': 0.6161437520654941,
 'f1': 0.6252904546494864}

Resultados¶

Generar dataframe que resume los resultados de los modelos de ML¶

In [34]:
with open("./Resultados/dict_df_modelos_all.pickle", "rb") as archivo:
    dict_cargado = pickle.load(archivo) 

pre_method_outlier=["cuartiles","z_score","trimming"]
mapeo_outlier={u:v for u,v in  zip(list(dict_cargado.keys()),pre_method_outlier)}

pre_method_correl=[1,0]
mapeo_correl={u:v for u,v in zip(list(dict_cargado["filtrar_outliers_trimming"].keys()),pre_method_correl)}

column_names = ['method_outlier', 'correl', 'method_scaled', 'Model_ML',"eva_train", 'eva_test',"accuracy","precision","recall","f1"]

# Crear un DataFrame vacío con las columnas especificadas
df = pd.DataFrame(columns=column_names)

for method_outlier in dict_cargado.keys():

    for method_correl in dict_cargado[method_outlier].keys():
        for method_scaled in dict_cargado[method_outlier][method_correl].keys():    
            if method_scaled=="without_escaled":
                continue
            print(method_outlier,method_correl,method_scaled)
            for model_ml in dict_cargado[method_outlier][method_correl][method_scaled]['Dict Modelos'].keys():
            
                nueva_fila=[]
                nueva_fila.append(mapeo_outlier[method_outlier])
                nueva_fila.append(mapeo_correl[method_correl])
                nueva_fila.append(method_scaled)
                nueva_fila.append(model_ml)
                nueva_fila.append(dict_cargado[method_outlier][method_correl][method_scaled]["Dict Modelos"][model_ml]["eva_train"])
                nueva_fila.append(dict_cargado[method_outlier][method_correl][method_scaled]["Dict Modelos"][model_ml]["eva_test"])
                nueva_fila.append(dict_cargado[method_outlier][method_correl][method_scaled]["Dict Modelos"][model_ml]["accuracy"])
                nueva_fila.append(dict_cargado[method_outlier][method_correl][method_scaled]["Dict Modelos"][model_ml]["precision"])
                nueva_fila.append(dict_cargado[method_outlier][method_correl][method_scaled]["Dict Modelos"][model_ml]["recall"])
                nueva_fila.append(dict_cargado[method_outlier][method_correl][method_scaled]["Dict Modelos"][model_ml]["f1"])
                
                df.loc[len(df)] = nueva_fila
        
with open("./Resultados/df_modelos_resumen.pickle", "wb") as archivo:
    pickle.dump(df, archivo)  
cuartiles filtrado_correlacion escaled_min_max
cuartiles filtrado_correlacion escaled_Standardization
cuartiles filtrado_correlacion robust_escaled_Standardization
cuartiles filtrado_correlacion diferenciado_escaled_min_max
cuartiles filtrado_correlacion diferenciado_escaled_Standardization
cuartiles filtrado_correlacion diferenciado_robust_escaled_Standardization
cuartiles no_filtrado_correlacion escaled_min_max
cuartiles no_filtrado_correlacion escaled_Standardization
cuartiles no_filtrado_correlacion robust_escaled_Standardization
cuartiles no_filtrado_correlacion diferenciado_escaled_min_max
cuartiles no_filtrado_correlacion diferenciado_escaled_Standardization
cuartiles no_filtrado_correlacion diferenciado_robust_escaled_Standardization
filtrar_outliers_zscore_dataframe filtrado_correlacion escaled_min_max
filtrar_outliers_zscore_dataframe filtrado_correlacion escaled_Standardization
filtrar_outliers_zscore_dataframe filtrado_correlacion robust_escaled_Standardization
filtrar_outliers_zscore_dataframe filtrado_correlacion diferenciado_escaled_min_max
filtrar_outliers_zscore_dataframe filtrado_correlacion diferenciado_escaled_Standardization
filtrar_outliers_zscore_dataframe filtrado_correlacion diferenciado_robust_escaled_Standardization
filtrar_outliers_zscore_dataframe no_filtrado_correlacion escaled_min_max
filtrar_outliers_zscore_dataframe no_filtrado_correlacion escaled_Standardization
filtrar_outliers_zscore_dataframe no_filtrado_correlacion robust_escaled_Standardization
filtrar_outliers_zscore_dataframe no_filtrado_correlacion diferenciado_escaled_min_max
filtrar_outliers_zscore_dataframe no_filtrado_correlacion diferenciado_escaled_Standardization
filtrar_outliers_zscore_dataframe no_filtrado_correlacion diferenciado_robust_escaled_Standardization
filtrar_outliers_trimming filtrado_correlacion escaled_min_max
filtrar_outliers_trimming filtrado_correlacion escaled_Standardization
filtrar_outliers_trimming filtrado_correlacion robust_escaled_Standardization
filtrar_outliers_trimming filtrado_correlacion diferenciado_escaled_min_max
filtrar_outliers_trimming filtrado_correlacion diferenciado_escaled_Standardization
filtrar_outliers_trimming filtrado_correlacion diferenciado_robust_escaled_Standardization
filtrar_outliers_trimming no_filtrado_correlacion escaled_min_max
filtrar_outliers_trimming no_filtrado_correlacion escaled_Standardization
filtrar_outliers_trimming no_filtrado_correlacion robust_escaled_Standardization
filtrar_outliers_trimming no_filtrado_correlacion diferenciado_escaled_min_max
filtrar_outliers_trimming no_filtrado_correlacion diferenciado_escaled_Standardization
filtrar_outliers_trimming no_filtrado_correlacion diferenciado_robust_escaled_Standardization

Mostrar mini resumen

In [35]:
with open("./Resultados/df_modelos_resumen.pickle", "rb") as archivo:
    df_modelos_resumen = pickle.load(archivo) 
df_modelos_resumen.head(3)
Out[35]:
method_outlier correl method_scaled Model_ML eva_train eva_test accuracy precision recall f1
0 cuartiles 1 escaled_min_max Ramdon Forest 1.000000 0.935103 0.825521 0.930821 0.822308 0.872143
1 cuartiles 1 escaled_min_max MultinomialNB 0.626302 0.585938 0.585938 0.615059 0.581192 0.592418
2 cuartiles 1 escaled_min_max MLPClassifier 1.000000 0.953728 0.947917 0.953296 0.964511 0.958466
In [36]:
# Mostrar los mejores modelos de ML
df_modelos_resumen.sort_values(by='f1', ascending=False).head(20)
Out[36]:
method_outlier correl method_scaled Model_ML eva_train eva_test accuracy precision recall f1
99 z_score 1 diferenciado_escaled_Standardization Ramdon Forest 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
210 trimming 0 diferenciado_escaled_Standardization Ramdon Forest 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
62 cuartiles 0 diferenciado_escaled_Standardization Ramdon Forest 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
173 trimming 1 diferenciado_escaled_Standardization Ramdon Forest 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
178 trimming 1 diferenciado_escaled_Standardization xgb.XGBClassifier 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
67 cuartiles 0 diferenciado_escaled_Standardization xgb.XGBClassifier 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
141 z_score 0 diferenciado_escaled_Standardization xgb.XGBClassifier 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
30 cuartiles 1 diferenciado_escaled_Standardization xgb.XGBClassifier 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
136 z_score 0 diferenciado_escaled_Standardization Ramdon Forest 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
25 cuartiles 1 diferenciado_escaled_Standardization Ramdon Forest 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
215 trimming 0 diferenciado_escaled_Standardization xgb.XGBClassifier 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
104 z_score 1 diferenciado_escaled_Standardization xgb.XGBClassifier 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
194 trimming 0 escaled_Standardization LinearSVC 0.992647 0.982405 0.982405 0.982166 0.980891 0.981462
200 trimming 0 robust_escaled_Standardization LinearSVC 0.988235 0.979472 0.979472 0.979116 0.977686 0.978273
9 cuartiles 1 escaled_Standardization LinearSVC 0.980469 0.971354 0.971354 0.971109 0.970064 0.970121
157 trimming 1 escaled_Standardization LinearSVC 0.970588 0.970674 0.970674 0.970220 0.969070 0.969562
147 z_score 0 diferenciado_robust_escaled_Standardization xgb.XGBClassifier 1.000000 0.986877 0.937028 0.987105 0.947269 0.966762
188 trimming 0 escaled_min_max LinearSVC 0.986029 0.967742 0.967742 0.967564 0.966283 0.966723
199 trimming 0 robust_escaled_Standardization MLPClassifier 1.000000 0.967647 0.953079 0.967745 0.964538 0.965985
114 z_score 0 escaled_min_max LinearSVC 0.979193 0.964736 0.964736 0.965006 0.965151 0.965032
In [ ]:
 
In [37]:
# Guardar en un dataframe los mejores modelos de ML
df_best_modelos=df_modelos_resumen.sort_values(by='f1', ascending=False).head(15).reset_index(drop=True)
df_best_modelos.head(2)
Out[37]:
method_outlier correl method_scaled Model_ML eva_train eva_test accuracy precision recall f1
0 z_score 1 diferenciado_escaled_Standardization Ramdon Forest 1.0 1.0 1.0 1.0 1.0 1.0
1 trimming 0 diferenciado_escaled_Standardization Ramdon Forest 1.0 1.0 1.0 1.0 1.0 1.0

Obtener los datos y modelos de los mejores modelos y guardarlos en un diccionario

In [38]:
with open("./Resultados/dict_df_modelos_all.pickle", "rb") as archivo:
    dict_cargado = pickle.load(archivo) 

pre_method_outlier=["cuartiles","z_score","trimming"]
mapeo_outlier={u:v for u,v in  zip(list(dict_cargado.keys()),pre_method_outlier)}
mapeo_outlier = {v: k for k, v in mapeo_outlier.items()}

pre_method_correl=[1,0]
mapeo_correl={u:v for u,v in zip(list(dict_cargado["filtrar_outliers_trimming"].keys()),pre_method_correl)}
mapeo_correl = {v: k for k, v in mapeo_correl.items()}

dict_modelos={}

for i in range(len(df_best_modelos)):

    method_outlier=df_best_modelos.iloc[i,:]["method_outlier"]
    correl=df_best_modelos.iloc[i,:]["correl"]
    method_scaled=df_best_modelos.iloc[i,:]["method_scaled"]
    mapeo_outlier[method_outlier],mapeo_correl[correl],method_scaled
    modelo=df_best_modelos.iloc[i,:]["Model_ML"]

    datos=dict_cargado[mapeo_outlier[method_outlier]][mapeo_correl[correl]][method_scaled]['Datos']
    config_model=dict_cargado[mapeo_outlier[method_outlier]][mapeo_correl[correl]][method_scaled]['Dict Modelos'][modelo]['best_model']
    
    dict_modelos[i]=[datos,config_model] 
In [39]:
# Mostrar ejemplo:
i=1
dict_modelos[i]=[datos,config_model] # diccionario que contiene los datos transformador y el modelo de ML entrenado 
df_best_modelos.head(2)   # Dataframe que contiene el rendimiento y transformación de los modelos de ML
Out[39]:
method_outlier correl method_scaled Model_ML eva_train eva_test accuracy precision recall f1
0 z_score 1 diferenciado_escaled_Standardization Ramdon Forest 1.0 1.0 1.0 1.0 1.0 1.0
1 trimming 0 diferenciado_escaled_Standardization Ramdon Forest 1.0 1.0 1.0 1.0 1.0 1.0

Mostrar medidas de rendimiento de los mejores modelos de ML¶

In [40]:
dic_var_dep={u:v for u,v in zip([(0,0,0,1),(0,1,0,0),(0,0,1,0),(1,0,0,0)],[0,1,2,3])}

l_accuracy_score,l_precision_score,l_recall_score,l_f1_score=[],[],[],[]

for i in list(dict_modelos.keys()):
    model_name=df_best_modelos.iloc[i,:]["Model_ML"]
    datos,model=dict_modelos[i]
    X_train , X_test , Y_train , Y_test, y_one_hot_train, y_one_hot_test=datos
    Y_test = list(Y_test)  # Y_test data series

    y_pred_test = model.predict(X_test)
    print("Modelo:", model_name)
    print(df_best_modelos.iloc[i,:])    
    if len(y_pred_test.shape)==2:
        y_pred_test_adj=[]
        for ii in range(len(list(y_pred_test))):
            if tuple(y_pred_test[ii,:])==(0, 1, 0, 1):
                print(y_pred_test[ii,:],ii)
            y_pred_test_adj.append(dic_var_dep[tuple(y_pred_test[ii,:])])
        y_pred_test=y_pred_test_adj

    
    matriz_confusion = confusion_matrix(Y_test, y_pred_test)
    precision = precision_score(Y_test, y_pred_test, average='micro')
    l_precision_score.append(precision)
    print("precision:", precision)

    recall = recall_score(Y_test, y_pred_test, average='weighted')  # También puedes cambiar 'weighted' a 'micro', 'macro', etc.
    print("Recall:", recall)
    l_recall_score.append(recall)

    # F1-score
    f1 = f1_score(Y_test, y_pred_test, average='weighted')  # También puedes cambiar 'weighted' a 'micro', 'macro', etc.
    print("F1-score:", f1)
    l_f1_score.append(f1)

    # Accuracy
    accuracy = accuracy_score(Y_test, y_pred_test)
    print("Accuracy:", accuracy)
    l_accuracy_score.append(accuracy)

    # Crear un mapa de calor con seaborn
    plt.figure(figsize=(4, 3))
    sns.heatmap(matriz_confusion, annot=True, fmt="d", cmap="Blues", cbar=False)
    plt.title("Matriz de Confusión")
    plt.xlabel("Predicciones")
    plt.ylabel("Valores Verdaderos")
    plt.show()            
    
Modelo: Ramdon Forest
method_outlier                                 z_score
correl                                               1
method_scaled     diferenciado_escaled_Standardization
Model_ML                                 Ramdon Forest
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 0, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: Ramdon Forest
method_outlier                                trimming
correl                                               0
method_scaled     diferenciado_escaled_Standardization
Model_ML                                 Ramdon Forest
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 1, dtype: object
precision: 0.9713541666666666
Recall: 0.9713541666666666
F1-score: 0.9711502665471755
Accuracy: 0.9713541666666666
Modelo: Ramdon Forest
method_outlier                               cuartiles
correl                                               0
method_scaled     diferenciado_escaled_Standardization
Model_ML                                 Ramdon Forest
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 2, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: Ramdon Forest
method_outlier                                trimming
correl                                               1
method_scaled     diferenciado_escaled_Standardization
Model_ML                                 Ramdon Forest
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 3, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: xgb.XGBClassifier
method_outlier                                trimming
correl                                               1
method_scaled     diferenciado_escaled_Standardization
Model_ML                             xgb.XGBClassifier
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 4, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: xgb.XGBClassifier
method_outlier                               cuartiles
correl                                               0
method_scaled     diferenciado_escaled_Standardization
Model_ML                             xgb.XGBClassifier
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 5, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: xgb.XGBClassifier
method_outlier                                 z_score
correl                                               0
method_scaled     diferenciado_escaled_Standardization
Model_ML                             xgb.XGBClassifier
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 6, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: xgb.XGBClassifier
method_outlier                               cuartiles
correl                                               1
method_scaled     diferenciado_escaled_Standardization
Model_ML                             xgb.XGBClassifier
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 7, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: Ramdon Forest
method_outlier                                 z_score
correl                                               0
method_scaled     diferenciado_escaled_Standardization
Model_ML                                 Ramdon Forest
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 8, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: Ramdon Forest
method_outlier                               cuartiles
correl                                               1
method_scaled     diferenciado_escaled_Standardization
Model_ML                                 Ramdon Forest
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 9, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: xgb.XGBClassifier
method_outlier                                trimming
correl                                               0
method_scaled     diferenciado_escaled_Standardization
Model_ML                             xgb.XGBClassifier
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 10, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: xgb.XGBClassifier
method_outlier                                 z_score
correl                                               1
method_scaled     diferenciado_escaled_Standardization
Model_ML                             xgb.XGBClassifier
eva_train                                          1.0
eva_test                                           1.0
accuracy                                           1.0
precision                                          1.0
recall                                             1.0
f1                                                 1.0
Name: 11, dtype: object
precision: 1.0
Recall: 1.0
F1-score: 1.0
Accuracy: 1.0
Modelo: LinearSVC
method_outlier                   trimming
correl                                  0
method_scaled     escaled_Standardization
Model_ML                        LinearSVC
eva_train                        0.992647
eva_test                         0.982405
accuracy                         0.982405
precision                        0.982166
recall                           0.980891
f1                               0.981462
Name: 12, dtype: object
precision: 0.9824046920821115
Recall: 0.9824046920821115
F1-score: 0.9823584459110223
Accuracy: 0.9824046920821115
Modelo: LinearSVC
method_outlier                          trimming
correl                                         0
method_scaled     robust_escaled_Standardization
Model_ML                               LinearSVC
eva_train                               0.988235
eva_test                                0.979472
accuracy                                0.979472
precision                               0.979116
recall                                  0.977686
f1                                      0.978273
Name: 13, dtype: object
precision: 0.9794721407624634
Recall: 0.9794721407624634
F1-score: 0.9794228652563222
Accuracy: 0.9794721407624634
Modelo: LinearSVC
method_outlier                  cuartiles
correl                                  1
method_scaled     escaled_Standardization
Model_ML                        LinearSVC
eva_train                        0.980469
eva_test                         0.971354
accuracy                         0.971354
precision                        0.971109
recall                           0.970064
f1                               0.970121
Name: 14, dtype: object
precision: 0.9713541666666666
Recall: 0.9713541666666666
F1-score: 0.9711502665471755
Accuracy: 0.9713541666666666

Hacer mapa de calor de las medidas de rendiemiento asociadas a los modelos de ML¶

In [41]:
df=df_best_modelos
df = df.drop(columns=['method_outlier',"correl","method_scaled"])
df = df.set_index('Model_ML')

sns.heatmap(df, cmap='mako',vmin=0.95,annot=True)
Out[41]:
<Axes: ylabel='Model_ML'>
In [42]:
df_worse_modelos=df_modelos_resumen.sort_values(by='f1', ascending=False).tail(15).reset_index(drop=True)
df=df_worse_modelos
df = df.drop(columns=['method_outlier',"correl","method_scaled"])
df = df.set_index('Model_ML')

sns.heatmap(df, cmap='mako',vmin=0.1,annot=True)
Out[42]:
<Axes: ylabel='Model_ML'>
In [43]:
prop_base=0.4
delta=0.1
cot_inf,cot_sup=int(len(df_modelos_resumen) * prop_base),int(len(df_modelos_resumen) * (prop_base+delta))

df_middle_modelos=df_modelos_resumen.sort_values(by='f1', ascending=False).iloc[cot_inf:cot_sup,:].reset_index(drop=True)
df=df_middle_modelos
df = df.drop(columns=['method_outlier',"correl","method_scaled"])
df = df.set_index('Model_ML')

sns.heatmap(df, cmap='mako',vmin=0.6,annot=True)
#df_worse_modelos
Out[43]:
<Axes: ylabel='Model_ML'>

Análisis de resultados:¶

Contexto:
Como se menciono al inicio este proyecto sólo busca mostrar las herramientas que se tiene para tratar los datos y modelos de ML, por lo tanto, las condiciones asociadas no fueron verificadas. Por ejemplo, si queremos usar z-score para eliminar los puntos outliers, entonces debemos verificar que los datos tengan distribución normal. La distribución normal de los datos se puede verificar utilizando una gráfica Q-Q, un test de hipotesis como el test de Shapiro.

Sección outliers:

  • En la sección de outliers vimos que la visualización de los boxplot es mucho mejor cuando utilizamos el paramétro "hue=range_price", esto se puede ver con un ejemplo, si una fila representativa de range_price="muy bajo" y la cantidad de bateria, entonces la cantidad de bateria deberia ser un outlier para los datos de tipo range_price="alto".

Sección Correlation Matrix:

  • En la sección Correlation Matrix vimos que sólo once columnas estaban correlacionadas con la columna de la variable dependiente, "range_prices".
  • Al eliminar las columnas no correlacionadas con la variable dependiente, "range_prices" notamos gran mejoría en los resultados de los modelos de clasificación. Es decir, los modelos de clasificación mejoraron sus resultados en general y se hicieron más rápidos de ejecutar. A parte de este punto, se reduce considerablemente el tiempo de entrenamiento.

Sección de Resultados:

  • En esta sección se pueden ver los resultados de todos los modelos. En esta sección, se tomo como instrumento de medida para ver el rendimiento del modelo a la medida "f1", pues esta ofrece un balance de medida entre los falsos positivos y falsos negativos. De aquí podemos determinar el rendimiento del modelo depende método de escalado (si es diferenciado o no) y el modelo de machine learning, en donde los modelos de random forest y XGBClassifier tuvieron mejores resultados.